﻿using IOA.MES.Client.Common;
using IOA.MES.Client.Models.Response;
using IOA.MES.Client.Settings;
using IOA.MES.Common;
using NLog;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Diagnostics;
using System.Reflection;
using System.IO;
using IOA.MES.Client.Common.SocketUtils;
using System.Drawing;
using System.Windows.Media;

namespace IOA.MES.Client.Framing
{
    /// <summary>
    /// FramingIndex.xaml 的交互逻辑
    /// </summary>
    public partial class FramingIndex : Window
    {
        private List<ViaSiteRecord> _records { get; set; } = new List<ViaSiteRecord>();
        private WinFramingImage _winImages = null;
        private string curDirectory;
        private string folder = string.Empty;
        private FileSystemWatcher dataFileWatcher;
        private int readImageDelay = 0;
        private SocketClient client;
        public FramingIndex()
        {
            InitializeComponent();
        }

        private void Window_Loaded(object sender, RoutedEventArgs e)
        {
            txtTrueName.Text = BaseEnv.UserInfo.TrueName;
            InitDuties();
            InitMachines();
            InitRecords();

            int.TryParse(BaseEnv.GetStorage("FrameReadImageDelay"), out readImageDelay);
            txtReadImageDelay.Text = readImageDelay.ToString();

            txtImageFolder.Text = BaseEnv.GetStorage("FrameScanImagesFolder") ?? string.Empty;
            cbScanImages.IsChecked = string.Equals(BaseEnv.GetStorage("FrameScanImagesChecked"), "1", StringComparison.CurrentCultureIgnoreCase);

            cbTakePhotos.IsChecked = true;
            cbScanBoxCode.IsChecked = false;
            txtBoxCode.IsEnabled = false;

            TryConnectTCP();
        }

        private void TryConnectTCP()
        {
            var ipAddress = BaseEnv.GetStorage("FrameIpAddress") ?? string.Empty;
            var port = BaseEnv.GetStorage("FramePort") ?? string.Empty;
            if (!string.IsNullOrWhiteSpace(ipAddress) && !string.IsNullOrWhiteSpace(port))
            {
                client = new SocketClient(this, ipAddress, Convert.ToInt32(port), OnTcpStatusChange, OnDataReceived, new List<byte> { 0x01, 0x00, 0x00 }, 10000);
                client.Connect();
            }
        }

        public void OnTcpStatusChange(bool connected)
        {
            if (connected)
            {
                txtLineStatus.Text = "已连接";
                txtLineStatus.Foreground = new SolidColorBrush(Colors.Green);
            }
            else
            {
                txtLineStatus.Text = "已断开";
                txtLineStatus.Foreground = new SolidColorBrush(Colors.Red);
            }
        }

        public void OnDataReceived(List<byte> data)
        {

        }

        private void Window_Closed(object sender, EventArgs e)
        {
            if (_winImages != null && PresentationSource.FromVisual(_winImages) != null)
            {
                _winImages.Close();
            }
            Environment.Exit(0);
        }

        private void cbTakePhotos_Checked(object sender, RoutedEventArgs e)
        {
            if (cbTakePhotos.IsChecked == true && cbScanImages.IsChecked != true)
            {
                this.WindowState = WindowState.Normal;
                this.Width = SystemParameters.WorkArea.Width / 3.0 * 2;
                this.Height = SystemParameters.WorkArea.Height;
                this.Left = 0;
                this.Top = 0;

                _winImages = new WinFramingImage();
                _winImages.Closed += _winImages_Closed;
                _winImages.Show();

                if (cbScanBoxCode.IsChecked == true)
                {
                    txtBoxCode.Focus();
                }
                else
                {
                    txtBarCode.Focus();
                }
            }
            else if (_winImages != null && PresentationSource.FromVisual(_winImages) != null)
            {
                this.WindowState = WindowState.Maximized;
                _winImages.Close();
            }
        }

        private void _winImages_Closed(object sender, EventArgs e)
        {
            this.WindowState = WindowState.Maximized;
            cbTakePhotos.IsChecked = false;
        }

        private void cbScanBoxCode_Checked(object sender, RoutedEventArgs e)
        {
            if (cbScanBoxCode.IsChecked == true)
            {
                txtBoxCode.IsEnabled = true;
            }
            else
            {
                txtBoxCode.IsEnabled = false;
            }
        }

        #region 初始化数据
        public void InitDuties()
        {
            var duties = BaseEnv.InvokeApi<QueryDutiesResponse>("/api/Auth/QueryDuties", new { WorkshopCode = BaseEnv.WorkshopCode }).Data.Duties;

            cbDuties.ItemsSource = duties;
            cbDuties.DisplayMemberPath = "DutyName";
            cbDuties.SelectedValuePath = "DutyId";

            if (duties.Any())
            {
                cbDuties.SelectedIndex = 0;
            }
        }

        public void InitMachines()
        {
            var machines = BaseEnv.InvokeApi<QueryMachinesResponse>("/api/Machine/QueryMachines", new { WorkshopCode = BaseEnv.WorkshopCode, MachineType = (int)MachineType.Framing }).Data.Machines;
            cbMachines.ItemsSource = machines;
            cbMachines.DisplayMemberPath = "MachineName";
            cbMachines.SelectedValuePath = "MachineId";

            if (machines.Any(_ => _.MachineId == BaseEnv.MachineId))
            {
                cbMachines.SelectedIndex = machines.FindIndex(_ => _.MachineId == BaseEnv.MachineId);
            }
            else
            {
                CommonMessage.Alert(this, "Vui lòng chọn lại thiết bị trong cài đặt hệ thống ngay bây giờ\r\n请先在系统设置中重新选择设备\r\nPlease reselect the device in the system settings now");
                new SettingsIndex().ShowDialog();
            }
        }

        private void InitRecords()
        {
            new TaskFactory().StartNew(() =>
            {
                Thread.Sleep(100);
                Dispatcher.Invoke(new Action(() =>
                {
                    var response = BaseEnv.InvokeApi<QueryViaSiteRecordsResponse>("/api/Machine/QueryViaSiteRecords", new { DutyId = Convert.ToInt32(cbDuties.SelectedValue), SiteType = SiteType.Framing, MachineId = Convert.ToInt32(cbMachines.SelectedValue) });
                    if (response.ErrCode != 200)
                    {
                        CommonMessage.Alert(this, response.ErrMsg);
                        return;
                    }
                    var records = response.Data.Records;
                    _records.Clear();
                    _records.AddRange(records);
                    _records.ForEach(_ => _.No = _records.Count - _records.IndexOf(_));
                    BindGridRecords();
                }));
            });
        }

        private void BindGridRecords()
        {
            gridRecords.ItemsSource = null;
            gridRecords.ItemsSource = _records;
            lbTotal.Content = _records.Select(_ => _.Code.ToUpper().Trim()).Distinct().Count();
        }
        #endregion

        /// <summary>
        /// 班次、机台选择
        /// </summary>
        private void cb_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            InitRecords();
        }

        /// <summary>
        /// 设置拍照延迟
        /// </summary>
        private void btnReadImageDelay_Click(object sender, RoutedEventArgs e)
        {
            if (string.IsNullOrWhiteSpace(txtReadImageDelay.Text))
            {
                txtReadImageDelay.Text = "0";
            }
            try
            {
                var delay = Convert.ToInt32(txtReadImageDelay.Text.Trim());
                readImageDelay = delay;
                BaseEnv.SetStorage("FrameReadImageDelay", delay.ToString());
            }
            catch (Exception ex)
            {
                CommonMessage.Alert(this, "请输入数字");
            }
        }

        /// <summary>
        /// 启用/禁用监控
        /// </summary>
        private void cbScanImages_Checked(object sender, RoutedEventArgs e)
        {
            txtBarCode.Text = "";
            if (cbScanImages.IsChecked == true)
            {
                BaseEnv.SetStorage("FrameScanImagesChecked", "1");
                txtBarCode.IsEnabled = false;
                if (!string.IsNullOrWhiteSpace(txtImageFolder.Text))
                {
                    WatchDataChanges(txtImageFolder.Text);
                }

                this.WindowState = WindowState.Maximized;
                if (_winImages != null && PresentationSource.FromVisual(_winImages) != null)
                {
                    _winImages.Close();
                }
            }
            else
            {
                BaseEnv.SetStorage("FrameScanImagesChecked", "0");
                txtBarCode.IsEnabled = true;
                txtBarCode.Focus();
                WatchDataChanges(txtImageFolder.Text, false);

                if (cbTakePhotos.IsChecked == true)
                {
                    this.WindowState = WindowState.Normal;
                    this.Width = SystemParameters.WorkArea.Width / 3.0 * 2;
                    this.Height = SystemParameters.WorkArea.Height;
                    this.Left = 0;
                    this.Top = 0;

                    _winImages = new WinFramingImage();
                    _winImages.Closed += _winImages_Closed;
                    _winImages.Show();
                }
            }
        }

        /// <summary>
        /// 选择监控路径
        /// </summary>
        private void btnSelectImageFile_Click(object sender, RoutedEventArgs e)
        {
            var dialog = new System.Windows.Forms.FolderBrowserDialog();
            if (dialog.ShowDialog() == System.Windows.Forms.DialogResult.OK && Directory.Exists(dialog.SelectedPath))
            {
                txtImageFolder.Text = dialog.SelectedPath;
                BaseEnv.SetStorage("FrameScanImagesFolder", dialog.SelectedPath);
                if (cbScanImages.IsChecked == true)
                {
                    WatchDataChanges(dialog.SelectedPath);
                }
            }
        }

        /// <summary>
        /// 开始监听图片文件
        /// </summary>
        private void WatchDataChanges(string folder, bool monitor = true)
        {
            if (monitor)
            {
                CommonMessage.Log(LogLevel.Debug, $"开始监听文件夹：{folder}");

                dataFileWatcher = new FileSystemWatcher(folder);
                dataFileWatcher.IncludeSubdirectories = true;
                dataFileWatcher.Created += DataFileWatcher_Changed;
                dataFileWatcher.EnableRaisingEvents = true;
                dataFileWatcher.NotifyFilter = NotifyFilters.Attributes | NotifyFilters.CreationTime | NotifyFilters.DirectoryName | NotifyFilters.FileName | NotifyFilters.LastAccess
                                       | NotifyFilters.LastWrite | NotifyFilters.Security | NotifyFilters.Size;
            }
            else
            {
                CommonMessage.Log(LogLevel.Debug, $"取消监听文件夹：{folder}");
                if (dataFileWatcher != null)
                {
                    dataFileWatcher.EnableRaisingEvents = false;
                }
            }
        }

        /// <summary>
        /// 文件变化监控
        /// </summary>
        private void DataFileWatcher_Changed(object sender, FileSystemEventArgs e)
        {
            CommonMessage.Log(LogLevel.Debug, $"发现文件【{e.ChangeType}】：{e.FullPath}");

            if (!new[] { ".jpg", ".jpeg", ".png", ".bmp" }.Contains(Path.GetExtension(e.FullPath), StringComparer.CurrentCultureIgnoreCase))
            {
                CommonMessage.Log(LogLevel.Debug, $"跳过文件：{e.FullPath}");
                return;
            }
            Thread.Sleep(readImageDelay * 1000);

            Dispatcher.Invoke(new Action(() =>
            {

                string[] stingArry = System.IO.Path.GetFileNameWithoutExtension(e.FullPath).Split('_');
                txtBarCode.Text = stingArry[1];
                //线盒拍照处命名：日期_条码_文件夹路径1层_文件夹路径2层....处理为取第一个下划线的后的值
                if (stingArry[stingArry.Length - 1].ToUpper() == "FMG")
                {
                    ViaSite(File.ReadAllBytes(e.FullPath));
                }
            }));
        }

        /// <summary>
        /// 扫描组件条码
        /// </summary>
        private void txtBarCode_KeyUp(object sender, KeyEventArgs e)
        {
            if (e.Key != Key.Enter || string.IsNullOrWhiteSpace(txtBarCode.Text.Trim()))
            {
                return;
            }

            Thread.Sleep(readImageDelay * 1000);
            var bytes = new byte[] { };
            if (cbTakePhotos.IsChecked == true)
            {
                bytes = _winImages.GetUnionImage(txtBarCode.Text.Trim().ToUpper(), (cbMachines.SelectedItem as Machine)?.MachineName ?? string.Empty);
            }

            ViaSite(bytes);
        }

        private void ViaSite(byte[] imageBuffer)
        {
            try
            {
                var image = string.Empty;
                if (imageBuffer != null && imageBuffer.Length > 0)
                {
                    var getComponentResponse = BaseEnv.InvokeApi<GetComponentResponse>("/api/Machine/GetComponent", new { BarCode = txtBarCode.Text.Trim() });
                    if (getComponentResponse.ErrCode != 200)
                    {
                        mediaElResult.Source = new Uri($"{BaseEnv.LocalDirectory}\\res\\audio\\Fail.wav");
                        mediaElResult.Play();
                        CommonMessage.Alert(this, getComponentResponse.ErrMsg);
                        return;
                    }
                    else if (getComponentResponse.Data == null || getComponentResponse.Data.Component == null)
                    {
                        mediaElResult.Source = new Uri($"{BaseEnv.LocalDirectory}\\res\\audio\\Fail.wav");
                        mediaElResult.Play();
                        CommonMessage.Alert(this, $"组件不存在\r\nComponent does not exist：\r\n{txtBarCode.Text.Trim()}");
                        return;
                    }
                    var tmpDirectory = $"/{BaseEnv.WorkshopCode}/framing/{getComponentResponse.Data.Component.WorkOrderNo}";
                    if (string.IsNullOrWhiteSpace(curDirectory) || !string.Equals(curDirectory, tmpDirectory, StringComparison.CurrentCultureIgnoreCase))
                    {
                        new FtpUtils(BaseEnv.UserInfo.FtpConfig.FtpRoot, BaseEnv.UserInfo.FtpConfig.UserName, BaseEnv.UserInfo.FtpConfig.Password).CheckAndCreateDirectory(tmpDirectory);
                        curDirectory = tmpDirectory;
                    }
                    var fileName = $"{curDirectory}/{txtBarCode.Text.Trim()}_{DateTime.Now:yyMMddHHmmss}.jpg";
                    Thread.Sleep(2000);
                    new FtpUtils(BaseEnv.UserInfo.FtpConfig.FtpRoot, BaseEnv.UserInfo.FtpConfig.UserName, BaseEnv.UserInfo.FtpConfig.Password).Upload(imageBuffer, fileName);
                    image = $"{BaseEnv.UserInfo.FtpConfig.FtpRoot}{fileName}";
                }

                var response = BaseEnv.InvokeApi<ViaSiteResponse>("/api/Machine/ViaSite", new
                {
                    SiteType = SiteType.Framing,
                    DutyId = Convert.ToInt32(cbDuties.SelectedValue),
                    MachineId = Convert.ToInt32(cbMachines.SelectedValue),
                    Code = txtBarCode.Text.Trim(),
                    BoxCode = txtBoxCode.Text.Trim(),
                    Images = new List<string> { image }
                });
                if (response.ErrCode != 200)
                {
                    mediaElResult.Source = new Uri($"{BaseEnv.LocalDirectory}\\res\\audio\\Fail.wav");
                    mediaElResult.Play();
                    CommonMessage.Alert(this, response.ErrMsg, false);
                    InitForms();
                    return;
                }
                mediaElResult.Source = new Uri($"{BaseEnv.LocalDirectory}\\res\\audio\\Success.wav");
                mediaElResult.Play();
                CommonMessage.Log(LogLevel.Info, $"过站成功：{txtBarCode.Text.Trim()}");

                txtWorkOrderNo.Text = response.Data.ViaSiteRecord.WorkOrderNo;

                if (response.Data.DutyId != Convert.ToInt32(cbDuties.SelectedValue))
                {
                    cbDuties.SelectedValue = response.Data.DutyId;
                }
                else
                {
                    response.Data.ViaSiteRecord.No = _records.Count + 1;
                    _records.Insert(0, response.Data.ViaSiteRecord);
                    BindGridRecords();
                }

                InitForms();
                if (txtLineStatus.Text.Equals("已连接"))
                {
                    client.Send(new List<byte> { 0x00, 0x01, 0x00 });
                }
            }
            catch (Exception ex)
            {
                CommonMessage.Alert(this, "软件异常，请拍照发给IT\r\nThe software is abnormal, please take a picture and send it to IT：\r\n" + ex.ToString(), false);
            }
        }

        /// <summary>
        /// 扫接线盒
        /// </summary>
        private void txtBoxCode_KeyUp(object sender, KeyEventArgs e)
        {
            txtBarCode.Focus();
        }

        private void InitForms()
        {
            txtBarCode.Text = "";
            txtBoxCode.Text = "";
            if (cbScanBoxCode.IsChecked == true)
            {
                txtBoxCode.Focus();
            }
            else
            {
                txtBarCode.Focus();
            }
        }

        private void Menu_Click(object sender, RoutedEventArgs e)
        {
            switch (((MenuItem)sender).Name)
            {
                case "btnSettings":
                    new SettingsIndex().ShowDialog();
                    break;
                case "btnMissingRecords":
                    new MissingSiteRecord(Convert.ToInt32(cbMachines.SelectedValue)).Show();
                    break;
                case "btnLineSetting":
                    if (new WinFrameSetting().ShowDialog() == true)
                    {
                        TryConnectTCP();
                    }
                    break;
                case "btnLogout":
                    new LoginWindow(false).Show();
                    this.Hide();
                    break;
                case "btnAbout":
                    MessageBox.Show($"AISUNMes Product Version:{FileVersionInfo.GetVersionInfo(Assembly.GetExecutingAssembly().Location).ProductVersion}");
                    break;
            }
        }

        private void Window_Closing(object sender, System.ComponentModel.CancelEventArgs e)
        {
            if (_winImages != null && PresentationSource.FromVisual(_winImages) != null)
            {
                _winImages.Close();
            }
        }
    }
}
